﻿#region Using
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
#endregion Using

namespace LloydGame
{
    public class ImageProcessor : GameComponent
    {
        #region Class Fields
        protected int m_imageWidth;
        protected int m_imageHeight;

        protected VertexDeclaration m_screenQuadVertexDecl = null;
        protected VertexPositionTexture[] m_screenQuadVerts = null;
        protected short[] m_screenQuadVertIndexData = new short[] { 0, 1, 2, 2, 3, 0 };

        protected Effect m_effect;

        protected DepthStencilBuffer m_depthStencil;
        #endregion Class Fields

        // constructor
        public ImageProcessor(Game p_game, int p_imageWidth, int p_imageHeight)
            : base(p_game)
        {
            m_imageWidth = p_imageWidth;
            m_imageHeight = p_imageHeight;

            // setup screen quad to draw image on
            m_screenQuadVertexDecl = new VertexDeclaration(
                p_game.GraphicsDevice,
                VertexPositionTexture.VertexElements);

            m_screenQuadVerts = new VertexPositionTexture[4];

            float dx = 1.0f / m_imageWidth;
            float dy = -1.0f / m_imageHeight;

            m_screenQuadVerts[0] = new VertexPositionTexture(new Vector3(1 - dx, -1 - dy, 0), new Vector2(1, 1));
            m_screenQuadVerts[1] = new VertexPositionTexture(new Vector3(-1 - dx, -1 - dy, 0), new Vector2(0, 1));
            m_screenQuadVerts[2] = new VertexPositionTexture(new Vector3(-1 - dx, 1 - dy, 0), new Vector2(0, 0));
            m_screenQuadVerts[3] = new VertexPositionTexture(new Vector3(1 - dx, 1 - dy, 0), new Vector2(1, 0));
        }

        // render the quad using pass p_n of the image processing effect
        protected void processPass(int p_n)
        {
            // backup the depth stencil buffer
            DepthStencilBuffer depthStencilBackup = Game.GraphicsDevice.DepthStencilBuffer;
            Game.GraphicsDevice.DepthStencilBuffer = m_depthStencil;

            Game.GraphicsDevice.VertexDeclaration = m_screenQuadVertexDecl;

            Game.GraphicsDevice.Clear(Color.White);

            m_effect.Begin();
            m_effect.CurrentTechnique.Passes[p_n].Begin();
            
            Game.GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionTexture>(
                PrimitiveType.TriangleList, m_screenQuadVerts, 0, 4, m_screenQuadVertIndexData, 0, 2);

            m_effect.CurrentTechnique.Passes[p_n].End();
            m_effect.End();

            // restore the depth stencil buffer
            Game.GraphicsDevice.DepthStencilBuffer = depthStencilBackup;
        }

        protected void setCornerFrustum()
        {
            // compute view frustum corner
            float farY = (float)Math.Tan(((Game1)Game).camera.fov / 2.0) * ((Game1)Game).camera.farClip;
            float farX = farY * ((Game1)Game).camera.aspectRatio;
            Vector3 cornerFrustum = new Vector3(farX, farY, ((Game1)Game).camera.farClip);

            m_effect.Parameters["cornerFustrum"].SetValue(cornerFrustum);
        }
    }
}
